Skip to content

fix(@angular/ssr): remove CSR fallback for invalid hosts#32579

Merged
alan-agius4 merged 1 commit intoangular:mainfrom
alan-agius4:ssr-csr-fallback
Feb 27, 2026
Merged

fix(@angular/ssr): remove CSR fallback for invalid hosts#32579
alan-agius4 merged 1 commit intoangular:mainfrom
alan-agius4:ssr-csr-fallback

Conversation

@alan-agius4
Copy link
Collaborator

Previously, when a request contained an unrecognized host header, the server would fallback to serving the client-side application (CSR) as a temporary migration path.

This commit removes this fallback behavior. Requests with invalid or unrecognized host headers will now strictly return a 400 Bad Request response.

BREAKING CHANGE: The server no longer falls back to Client-Side Rendering (CSR) when a request fails host validation. Requests with unrecognized headers will now return a 400 Bad Request status code. Users must ensure all valid hosts are correctly configured in the option.

@alan-agius4 alan-agius4 requested a review from dgp1130 February 25, 2026 13:50
@alan-agius4 alan-agius4 added action: review The PR is still awaiting reviews from at least one requested reviewer target: major This PR is targeted for the next major release labels Feb 25, 2026
@angular-robot angular-robot bot added detected: breaking change PR contains a commit with a breaking change area: @angular/ssr labels Feb 25, 2026
Previously, when a request contained an unrecognized host header, the server would fallback to serving the client-side application (CSR) as a temporary migration path.

This commit removes this fallback behavior. Requests with invalid or unrecognized host headers will now strictly return a 400 Bad Request response.

BREAKING CHANGE: The server no longer falls back to Client-Side Rendering (CSR) when a request fails host validation. Requests with unrecognized 'Host' headers will now return a 400 Bad Request status code. Users must ensure all valid hosts are correctly configured in the 'allowedHosts' option.
Copy link
Collaborator

@dgp1130 dgp1130 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM for this change, but at a higher level, I'm a bit worried this could present very breaking behavior for most apps.

IIUC: If a developer doesn't do anything (just ng update), and blindly updates to the next major, they won't get any CI failures or local issues, but upon deploying they will fail all requests. That could catch a lot devs off guard. Is that an accurate assessment of the new behavior?

It's tricky to find a balance which makes this a visible breakage for existing apps while also support new developers creating a new app and not wanting to think about hostnames yet.

Two alternatives I can think of:

  1. Validate allowedHosts at startup (maybe limited to production builds?), so the server fails to even start without it. That would hopefully trigger a CI error in most environments and be visible locally.
  2. Add some kind of allowEmptyHostsInDev option and enable it automatically in ng new, but then cause a type error for allowedHosts: undefined | [], allowEmptyHostsInDev: false | undefined. This way upgrading apps would get a compile-error that a host needs to be specified while not blocking new apps from dev. Then once we're sure all existing apps have a host listed, we can drop allowEmptyHostsInDev in the next major.

Do either of those options make sense? Is there a path to making this new constraint up front and visible to migrating apps?

Comment on lines 96 to 98
console.error(
`ERROR: ${(error as Error).message}` +
'Please provide a list of allowed hosts in the "allowedHosts" option in the "CommonEngine" constructor.',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider: Do we still want a separate log statement since we have an unconditionalthrow below? I feel like this would result in double-logging this error under more circumstances.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case the throw will be passed to the express error which will not print the message in the console.

@alan-agius4
Copy link
Collaborator Author

Validate allowedHosts at startup (maybe limited to production builds?), so the server fails to even start without it. That would hopefully trigger a CI error in most environments and be visible locally.

This isn't feasible because allowedHosts can be configured through both the options object and environment variables and sense a build failure both during ng build and ng serve is not a possibility.

Add some kind of allowEmptyHostsInDev option and enable it automatically in ng new, but then cause a type error for `allowedHosts: undefined | [], allowEmptyHostsInDev: false | undefined. This way upgrading apps would get a compile-error that a host needs to be specified while not blocking new apps from dev. Then once we're sure all existing apps have a host listed, we can drop allowEmptyHostsInDev in the next major.

Again a build error is not feasible here due to the same thing as described above, in dev-server, we pass the Vite's allowedHost or the provided host that is provided to vite to the SSR engine. A hostname (defaults to localhost) is always needed for the dev-server so the hostname is known. One thing we do not handle is 0.0.0.0 and connecting to the dev-server with external IPs. The dev-server already has an opton --allowed-host which accepts a boolean and disables host checking. I think potentially we could leverage that. I'll try to followup.

@alan-agius4 alan-agius4 added action: merge The PR is ready for merge by the caretaker and removed action: review The PR is still awaiting reviews from at least one requested reviewer labels Feb 27, 2026
@alan-agius4 alan-agius4 merged commit 27cd355 into angular:main Feb 27, 2026
34 of 35 checks passed
@alan-agius4
Copy link
Collaborator Author

This PR was merged into the repository. The changes were merged into the following branches:

@alan-agius4 alan-agius4 deleted the ssr-csr-fallback branch February 27, 2026 08:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action: merge The PR is ready for merge by the caretaker area: @angular/ssr detected: breaking change PR contains a commit with a breaking change target: major This PR is targeted for the next major release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants